﻿
Imports System.Net
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.envs
Imports osi.root.formation
Imports osi.root.lock
Imports osi.root.utils
Imports osi.root.procedure
Imports osi.service.convertor
Imports osi.service.configuration
Imports osi.service.storage
Imports osi.service.tcp
Imports osi.service.http
Imports osi.service.commander
Imports configuration = osi.service.storage.configuration
Imports tcpd = osi.service.tcp.constants.default_value
Imports httpd = osi.service.http.constants.default_value

Public Module _init
    Private ReadOnly dispatcher As target_dispatcher(Of String, istrkeyvt)

    Sub New()
        dispatcher = istrkeyvt_responder.create_target_dispatcher(New dispatcher())
        assert(istrkeyvt_responder.listen(dispatcher))
    End Sub

    Private Sub load_preserved_disk()
        Dim s As section = Nothing
        s = config("preserved_disk")
        If Not s Is Nothing Then
            Dim keys As vector(Of String) = Nothing
            keys = s.keys()
            If Not keys Is Nothing AndAlso
               Not keys.empty() Then
                For i As UInt32 = 0 To CUInt(keys.size() - 1)
                    Dim v As UInt64 = 0
                    v = s(keys(i)).to_uint64()
                    configuration.preserved_disk_capacity(keys(i)) = v
                Next
            End If
        End If
    End Sub

    Public Function load_istrkeyvt(ByVal s As section,
                                   Optional ByVal r As pointer(Of istrkeyvt) = Nothing) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  assert(Not s Is Nothing)
                                  Dim name As String = Nothing
                                  Dim type As String = Nothing
                                  assert(s.get("name", name),
                                         s.get("type", type))
                                  r.renew()
                                  Using New regional_environments({{"data", data_folder},
                                                                   {"service", service_name},
                                                                   {"service_data", service_data_folder}})
                                      ec = resolve(name, type, s("parameter").env_transform(), r)
                                  End Using
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Private Sub load_istrkeyvt()
        Dim ss As vector(Of section) = Nothing
        ss = config.sections("istrkeyvt")
        assert(Not ss Is Nothing)
        If Not ss.empty() Then
            Dim loaded As atomic_int = Nothing
            loaded = New atomic_int()
            For i As UInt32 = 0 To CUInt(ss.size() - 1)
                Dim ec As event_comb = Nothing
                Dim s As section = Nothing
                s = ss(i)
                assert_begin(New event_comb(Function() As Boolean
                                                ec = load_istrkeyvt(s)
                                                Return waitfor(ec) AndAlso
                                                       goto_next()
                                            End Function,
                                            Function() As Boolean
                                                assert(ec.end_result())
                                                loaded.increment()
                                                Return goto_end()
                                            End Function))
            Next
            timeslice_sleep_wait_until(Function() (+loaded) = ss.size())
        End If
    End Sub

    Private Function load_tcp_server(ByVal s As section, Optional ByRef pp As powerpoint = Nothing) As Boolean
        assert(Not s Is Nothing)
        Dim is_outgoing As String = Nothing
        Dim host As String = Nothing
        Dim port As String = Nothing
        Dim token As String = Nothing
        Dim max_connecting As String = Nothing
        Dim max_connected As String = Nothing
        Dim no_delay As String = Nothing
        Dim connecting_timeout_ms As String = Nothing
        Dim response_timeout_ms As String = Nothing
        Dim send_rate_sec As String = Nothing
        Dim receive_rate_sec As String = Nothing
        Dim max_lifetime_ms As String = Nothing
        Dim ipv4 As String = Nothing
        Dim enable_keepalive As String = Nothing
        Dim first_keepalive_ms As String = Nothing
        Dim keepalive_interval_ms As String = Nothing
        Dim zipper As String = Nothing
        Dim encryptor As String = Nothing
        If s.parse_tcp_parameters(is_outgoing,
                                  host,
                                  port,
                                  Nothing,
                                  token,
                                  max_connecting,
                                  max_connected,
                                  no_delay,
                                  connecting_timeout_ms,
                                  response_timeout_ms,
                                  send_rate_sec,
                                  receive_rate_sec,
                                  max_lifetime_ms,
                                  ipv4,
                                  enable_keepalive,
                                  first_keepalive_ms,
                                  keepalive_interval_ms,
                                  zipper,
                                  encryptor) AndAlso
           powerpoint.create(token,
                             host,
                             port,
                             ipv4,
                             connecting_timeout_ms,
                             send_rate_sec,
                             response_timeout_ms,
                             receive_rate_sec,
                             max_connecting,
                             max_connected,
                             no_delay,
                             max_lifetime_ms,
                             is_outgoing,
                             enable_keepalive,
                             first_keepalive_ms,
                             keepalive_interval_ms,
                             zipper,
                             encryptor,
                             pp) Then
            Dim responder As tcp_responder = Nothing
            responder = New tcp_responder(+dispatcher)
            Return answer(pp, AddressOf responder.handler)
        Else
            Return False
        End If
    End Function

    Private Function load_http_server(ByVal s As section, Optional ByRef srv As server = Nothing) As Boolean
        assert(Not s Is Nothing)
        Dim max_connection_count As String = Nothing
        Dim response_timeout_ms As String = Nothing
        Dim port As String = Nothing
        Dim buff_size As String = Nothing
        Dim single_copy_timeout_ms As String = Nothing
        Dim copy_timeout_ms As String = Nothing
        Dim max_content_length As String = Nothing
        If s.parse_http_parameters(Nothing,
                                   port,
                                   Nothing,
                                   max_connection_count,
                                   Nothing,
                                   response_timeout_ms,
                                   buff_size,
                                   single_copy_timeout_ms,
                                   copy_timeout_ms,
                                   max_content_length) Then
            srv = New server(max_connection_count, response_timeout_ms)
            If srv.add_port(port) AndAlso
               srv.start() Then
                Dim ls As link_status = Nothing
                ls = New link_status(Nothing,
                                     buff_size,
                                     single_copy_timeout_ms,
                                     copy_timeout_ms,
                                     max_content_length)
                Dim responder As http_responder = Nothing
                responder = New http_responder(+dispatcher)
                responder.read_request_body_as_string.set_local(Function(ctx As HttpListenerContext,
                                                                         o As pointer(Of String)) As event_comb
                                                                    Return read_request_body_as_string(ctx, o, ls)
                                                                End Function)
                AddHandler srv.handle_context, AddressOf responder.handler
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function

    Public Function load_server(ByVal s As section,
                                Optional ByRef pp As powerpoint = Nothing,
                                Optional ByRef srv As server = Nothing) As Boolean
        assert(Not s Is Nothing)
        If strsame(s("type"), "tcp", False) Then
            Return load_tcp_server(s, pp)
        Else
            Return load_http_server(s, srv)
        End If
    End Function

    Private Sub load_server()
        Dim ss As vector(Of section) = Nothing
        ss = config.sections("server")
        assert(Not ss Is Nothing)
        If Not ss.empty() Then
            Dim loaded As atomic_int = Nothing
            loaded = New atomic_int()
            For i As UInt32 = 0 To CUInt(ss.size() - 1)
                Dim r As Boolean = False
                Dim s As section = Nothing
                s = ss(i)
                assert_begin(New event_comb(Function() As Boolean
                                                Return waitfor(Sub()
                                                                   r = load_server(s)
                                                               End Sub) AndAlso
                                                       goto_next()
                                            End Function,
                                            Function() As Boolean
                                                assert(r)
                                                loaded.increment()
                                                Return goto_end()
                                            End Function))
            Next
            timeslice_sleep_wait_until(Function() (+loaded) = ss.size())
        End If
    End Sub

    Public Sub init()
        load_preserved_disk()
        load_istrkeyvt()
        load_server()
    End Sub
End Module
